﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;

namespace BitTorrentSharp.Peers
{
	/// <summary>
	/// Helper class for byte operations. This is a static class.
	/// </summary>
	internal static class ByteHelper
	{
		/// <summary>
		/// Repressent as a empty byte sequence. This field is read-only.
		/// </summary>
		public static readonly byte[] EmptyData = new byte[0];

		/// <summary>
		/// Make sure the data sequnce is in big-endian.
		/// </summary>
		/// <param name="data">The data to be checked. If the data is actually big-endian, nothing will happen. If the data is little-endian, the data sequence will be reversed.</param>
		/// <returns>The input <paramref name="data"/> argument. This method will not create a new byte array.</returns>
		/// <remarks>This method uses <see cref="BitConverter.IsLittleEndian"/> to check if the system bit order is in little-endian.</remarks>
		public static byte[] EnsureBigEndian(this byte[] data)
		{
			// TODO: Consider to remove null-check in order to improve the performance.
			if (data == null)
			{
				throw new ArgumentNullException("data");
			}

			Contract.EndContractBlock();

			// TODO: Consider to improve the performance using some other routing.
			if (BitConverter.IsLittleEndian)
			{
				Array.Reverse(data);
			}

			return data;
		}

		/// <summary>
		/// Concat multiple byte arrays to a single array.
		/// </summary>
		/// <param name="datas">The array of data array to be concated.</param>
		/// <returns>The concated single data array.</returns>
		public static byte[] Concat(params byte[][] datas)
		{
			if (datas == null)
			{
				throw new ArgumentNullException("datas");
			}

			// Get the total length;
			var length = datas.Sum(i => i.Length);

			var start = 0;

			var result = new byte[length];

			foreach (var arr in datas)
			{
				// Use buffer class to improve performance.
				Buffer.BlockCopy(arr, 0, result, start, arr.Length);
				start += arr.Length;
			}

			return result;
		}
	}
}
